package com.a0soft.gphone.aTruffleHog.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESEncryptor {
    private static final String IV = CONFIGURATION.AES_LV_PARAMS;
    private static final String KEYGEN_ALGORITHM = "AES";
    private static final String CIPHER_ALGORITHM = "AES/CBC/NoPadding";
    private static final String HEADER = CONFIGURATION.AES_DATA_HEADER;
    
    private static final String LOG_TAG = AESEncryptor.class.getSimpleName();
    
    public static String
    Encrypt(String strSrc, String strKey)
    {
        try {
            strSrc = HEADER + strSrc;
            strKey = MiscUtil.MD5(strKey);
            //if (aDebug.ENABLED)
            //    aDebug.d(LOG_TAG, "md5 key=" + strKey);
            IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
            
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, 
                        new SecretKeySpec(strKey.getBytes(), KEYGEN_ALGORITHM), 
                        ivspec);
            return _BytesToHex(cipher.doFinal(_PadString(strSrc).getBytes()));
        }
        catch (Exception e) {
            if (aDebug.ENABLED)
                aDebug.e(LOG_TAG, "Encrypt()", e);
        }
        return null;
    }
    
    public static String
    Decrypt(String strSrc, String strKey)
    {
        try {
            strKey = MiscUtil.MD5(strKey);
            IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
        
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, 
                        new SecretKeySpec(strKey.getBytes(), KEYGEN_ALGORITHM), 
                        ivspec);
            //byte[] bytes = new BigInteger(text, 16).toByteArray(); //has bug
            byte[] bytes = _HexToBytes(strSrc);
            if (aDebug.ENABLED)
                aDebug.d(LOG_TAG, "bytes len=" + bytes.length);
            String str = new String(cipher.doFinal(bytes));
            if (str.startsWith(HEADER))
                return str.substring(HEADER.length());
            else {
                if (aDebug.ENABLED)
                    aDebug.d(LOG_TAG, "Decrypt(): not start with " + HEADER);
            }
        }
        catch (Exception e) {
            if (aDebug.ENABLED)
                aDebug.e(LOG_TAG, "Decrypt()", e);
        }
        return null;
    }
    
    private static String 
    _PadString(String strSrc) 
    {
        final int nSrcLen = strSrc.length();
        final int SIZE = 16;
        final int nPadLen = SIZE - (nSrcLen % SIZE);
        if (nPadLen == 0) return strSrc;
        
        StringBuilder sb = new StringBuilder(nSrcLen + nPadLen);
        sb.append(strSrc);
        for (int i = 0; i < nPadLen; i++) {
            sb.append(' ');
        }        
        return sb.toString();
    }
    
    private static String
    _BytesToHex(byte[] bytes)
    {
        final String HEXINDEX = "0123456789abcdef";
        final int nSize = bytes.length;
        StringBuilder sb = new StringBuilder(nSize * 2);
        for (int i = 0; i < nSize; i++) {
            byte b = bytes[i];
            sb.append(HEXINDEX.charAt((b & 0xf0) >> 4));
            sb.append(HEXINDEX.charAt(b & 0xf));
        }
        return sb.toString();
    }
    
    private static byte[] 
    _HexToBytes(String strIn) 
    {
        final String HEXINDEX = "0123456789abcdef";
        final int nLen = strIn.length() / 2;
        byte data[] = new byte[nLen];
        int j = 0;

        for (int i = 0; i < nLen; i++) {
            char c = strIn.charAt(j++);
            int n, b;

            n = HEXINDEX.indexOf(c);
            b = (n & 0xf) << 4;
            c = strIn.charAt(j++);
            n = HEXINDEX.indexOf(c);
            b += (n & 0xf);
            data[i] = (byte)b;
        }

        return data;
    }
}
